package net.oschina.bilbodai.common.beanutil.property;

import net.oschina.bilbodai.common.beanutil.property.asm.lexer.code.mp.MapValueType;
import net.oschina.bilbodai.common.beanutil.util.StringUtil;

/**
 * <pre>
 *     1. 以 '#' 开头如 '#globalOrderType' 会去{@link ValueTypeMappingFactory#bindType(String, Class)} 注册的类型寻找
 *     '#order#orderType' 则会去{@link ValueTypeMappingFactory#registerValueTypeMapping(String, IValueTypeMapping)} 中注册的实例中找
 *     2. 如果以 '@' 开头, 如 '@java/lang/String' 则会根据 'java.lang.String' 调用 {@link Class#forName(String)} 去找
 *     3. 否则根据 {@link MapValueType#type(String)} 中的枚举字面值得到
 *     4. 否则报错
 * </pre>
 *
 * @author daimao  Date: 16/4/22 Time: 下午5:10
 * @version $Id$
 */
public class ValueTypeMappings {

    // "lookup@java.lang.String"
    // 注意所有的字符规则不能使用token的 ", [ ]" 中的任意字符
    private static final String LOOK_UP_NAME = "lookup";
    private static final String LOOK_UP_PREFIX = "@";

    private static final String EXTERNAL_LOOK_UP_PREFIX = "#";
    private static final String EXTERNAL_LOOK_UP_ID_SEPARATOR = "#";

    public static Class<?> getMapValueType(String type) {

        if (type.startsWith(EXTERNAL_LOOK_UP_PREFIX)) {
            String nameId = type.substring(1);
            int lookupIdSeparatorIndex = nameId.indexOf(EXTERNAL_LOOK_UP_ID_SEPARATOR);
            Class<?> valueType;
            if (lookupIdSeparatorIndex == -1) {
                //使用GlobalName
                valueType = ValueTypeMappingFactory.findGlobalType(nameId);
            } else {
                String mappingId = nameId.substring(0, lookupIdSeparatorIndex);
                String localNameId = nameId.substring(lookupIdSeparatorIndex + 1);
                valueType = ValueTypeMappingFactory.findTypeByName(mappingId, localNameId);
            }
            if (valueType == null) {
                throw new RuntimeException("No External MapValue Referenced by MapValueName:'" + nameId);
            }
            return valueType;
        }

        String mapValueName = type;
        String customMapValueType = "";
        if (type.startsWith(LOOK_UP_PREFIX)) {
            mapValueName = LOOK_UP_NAME;
            customMapValueType = type.substring(1);
            if (StringUtil.isEmpty(customMapValueType)) {
                throw new IllegalArgumentException("Lookup Custom Class Name must not be empty!");
            }
        }
        MapValueType mapValueType = null;
        try {
            mapValueType = MapValueType.valueOf(mapValueName);
        } catch (IllegalArgumentException e) {
            throw new RuntimeException("No MapValue Referenced by MapValueName:'" + mapValueName + "' and CustomMapValueType:'" + customMapValueType + "'.");
        }
        return mapValueType.type(customMapValueType);
    }
}